#include "buzz.h"
#include "timer.h"
#include "global.h"

/* Macro definition */
#define TIMER_0_PRESCALER                   SYSCLK_SCA_PRESCALER
#define TIMER_PWM_SLSEL                     256
#define TIMER_PWM_TICKS_PER_S               SYSCLK/TIMER_0_PRESCALER/TIMER_PWM_SLSEL
#define TIMER_PWM_FREQ(freq)                (TIMER_PWM_TICKS_PER_S/freq)


#define BUZZ_TIMER_START(timeout)           user_timer_restart(USER_TIMER_BUZZ,timeout,buzz_timeout_handler);
#define BUZZ_TIMER_STOP()                   user_timer_stop(USER_TIMER_BUZZ);
#define BUZZ_TIMER_CREATE()

#define BUZZ_PWM_INIT()                     (PCA0PWM |= (PCA0PWM_ARSEL__BMASK | PCA0PWM_CLSEL__8_BITS))

#define BUZZ_PWM_STOP()          									        \
{                         		\
  	TMR2CN0 &= ~TMR2CN0_TR2__BMASK;									\
	TCON &= ~ TCON_TR0__BMASK;										\
	TCON &= ~ TCON_TF0__BMASK;										\
}

#define BUZZ_PWM_SET_FREQ_DUTY_CYCLE(pwm_freq,duty_cycle_percent)           \
{                                                                           \
    uint8_t TCON_save = TCON;                                               \
    TCON &= TCON_TR0__BMASK;                              \
    TL0 =  0x00;                                                            \
    TH0 = (0xff- TIMER_PWM_FREQ(pwm_freq));                                 \
    TCON = TCON_save;                                                       \
    TCON |= TCON_TR0__RUN;													\
}


#define BUZZ_3200                       (1046)

#define BZ_MS(para)                     (para)

const int BUZZ_DIDI[] =
{
    BUZZ_3200, BZ_MS(125),
    0          , BZ_MS(125),
    BUZZ_3200, BZ_MS(125),
    0          , -1,
};


/* Local Variables */
static int m_sample_level;
static int m_capture_time;
static const int *m_music_index = NULL;

static volatile bool is_buzz_driving_flag = false;

/* Internal functions declaration */
static void buzz_timeout_handler(void);

/* Public functions */

/************************************************************
 * @brief buzz_init
************************************************************/
int buzz_init(void)
{
	BUZZ_PWM_INIT();
    //鍒涘缓寤舵椂buzz鐨則imer
    BUZZ_TIMER_CREATE();
    return 0;
}

/************************************************************
 * @brief buzz_shutdown
************************************************************/
int buzz_shutdown(void)
{
    BUZZ_TIMER_STOP();

    m_sample_level = 0;
    m_capture_time = 0;
    m_music_index = NULL;

    BUZZ_PWM_STOP();
    return 0;
}

/************************************************************
 * @brief buzz_start
************************************************************/
int buzz_start(const int buzz_array[])
{
    buzz_shutdown();

    m_music_index = buzz_array;

    BUZZ_TIMER_START(10);

    return 0;
}

/************************************************************
 * @brief buzz_start_bass
************************************************************/
void buzz_start_bass(const int buzz_array[])
{
    //LOG("銆恇uzz_start_bass銆�%d - %d",level,m_buzz_level);
    buzz_shutdown();

    m_music_index = buzz_array;

    BUZZ_TIMER_START(10);
}


/************************************************************
 * @brief ble_buzz_timeout_handler
************************************************************/
static void buzz_timeout_handler(void)
{
    //LOG("ble_buzz_timeout_handler");
    static bool buzz_stop_flag = false;

    if(m_music_index != NULL)
    {
        m_sample_level = *(m_music_index);
        m_capture_time = *(m_music_index + 1);

        if( (m_sample_level == 0) && (m_capture_time < 0) )
        {
            buzz_stop_flag = true;
        }
        else
        {
            if(m_sample_level != 0)
            {
                BUZZ_PWM_INIT();
                BUZZ_PWM_SET_FREQ_DUTY_CYCLE((uint32_t)(m_sample_level),(uint8_t)50);
            }
            else
            {
                BUZZ_TIMER_STOP();
                BUZZ_PWM_STOP();
            }

            BUZZ_TIMER_START(m_capture_time);

            m_music_index += 2;
        }
    }
    else
    {
        buzz_stop_flag = true;
    }

    if(buzz_stop_flag == true)
    {
        buzz_stop_flag = false;
        buzz_shutdown();
    }
}
